//////////////////////////////////////////////////////////////////
// MattiseOS Kernel
// Date: 2008
// Author: Matthew Iselin
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//////////////////////////////////////////////////////////////////

// Includes
#include <mattise.h>
#include <stdint.h>
#include <string.h>
#include <mem/util.h>
#include <mem/heap.h>
#include <mem/page.h>
#include <exec/elf.h>
#include <kernio/io.h>
#include <core/portio.h>
#include <process/common.h>
#include <core/intrcommon.h>

// Defines

// ...

// Functions

// executes a process, replacing the parent address space with the new process
// one (ie, go through, unmap all non-kernel pages, load new)
int execve( char* name, char** argv, char** UNUSED(env) )
{
	// checks
	if(name == 0)
		return -1;
	int fd = sys_open(name, 0);
	if(fd < 0)
		return -1;
	sys_close(fd);

	// ensure the arguments are copied to the kernel, so they can be transferred
	if(argv)
	{
		int argc = 0, arg = 0;
		for(argc = 0; argv[argc] != 0; argc++);

		char** new_argv = (char**) malloc(sizeof(char*) * (argc + 1));
		for(arg = 0; arg < argc; arg++)
		{
			new_argv[arg] = (char*) malloc(strlen(argv[arg]) + 1);
			memcpy(new_argv[arg], argv[arg], strlen(argv[arg]) + 1);
		}
		new_argv[arg] = 0;

		argv = new_argv;
	}

	// load it
    int32_t ret = LoadStaticBinaryFromFile( name, GetKernelDirectory(), TF_USPACE, 0, argv );

    // replacing the calling process means this is now irrelevant
    return ret;
}
